package com.widowcrawler.core.retry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Random;
import java.util.function.Supplier;
/**
* Provides a generic way to perform synchronous, randomized, exponential-backoff operations.
*
* @author Scott Mansfield
*/
public class Retry {
private static final Logger logger = LoggerFactory.getLogger(Retry.class);
private static final Random random = new Random();
private static final Integer DEFAULT_RETRY_COUNT = 3;
private static final Integer VARIANCE = 10000;
public static <T> T retry(Supplier<T> tryMe) throws InterruptedException, RetryFailedException {
return retry(tryMe, DEFAULT_RETRY_COUNT);
}
public static <T> T retry(Supplier<T> tryMe, int times) throws InterruptedException, RetryFailedException {
Throwable latestError = null;
for (int i = 1; i <= times; i++) {
try {
logger.info("Trying time " + i);
return tryMe.get();
} catch (Throwable t) {
logger.error("Error while (re)trying ", t);
latestError = t;
}
if (i < times) {
int sleepTime = random.nextInt(VARIANCE) + (i * i * 1000);
logger.info("Sleeping for " + sleepTime + "ms");
Thread.sleep(sleepTime);
}
}
throw new RetryFailedException("Retry could not complete the operation", latestError);
}
}